// Ninf-G-XX, ver. 0.1
// Copyright 2011 National Institute of Advanced Industrial Science and Technology
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __NC_GEN_H__
#define __NC_GEN_H__

#include <vector>
#include <stdarg.h>
#include <cstring>

#include "FunctionEntry.hpp"

#define FORTRAN "fortran"
#define FORTRAN_STRING_CONVENTION_LAST          0
#define FORTRAN_STRING_CONVENTION_JUST_AFTER    1

#define TARGET_UNIVERSE_STANDARD                0
#define TARGET_UNIVERSE_VANILLA                 1

#define CONDOR_COMPILE "condor_compile"

namespace ninf {
	namespace gen {
		class GenGlobals {
		public:
			int    lineno;
			
			const char * sourceFilename;
			const char * outputFilename;
			FILE * sourceFp;
			FILE * outputFp;
			
			bool   debug;
			FILE * debugFp;
			
			std::vector <const char *> libs;
			std::vector <const char *> globals;
			std::vector <const char *> compileOptions;
			
			const char * compilerName;
			const char * linkerName;
			int    fortranStringConvention;
			const char * currentFortranFormat;
			const char * currentModule;
			
			bool   gmake;
			
			int    universe;
			
			std::vector <ninf::lib::FunctionEntry *> stubs;
			
			GenGlobals():
				lineno(0), 
				sourceFilename(NULL),
				outputFilename(NULL),
				sourceFp(NULL),
				outputFp(NULL),
				debug(false),
				debugFp(NULL),
				compilerName(NULL),
				linkerName(NULL),
				fortranStringConvention(FORTRAN_STRING_CONVENTION_JUST_AFTER),
				currentFortranFormat(NULL),
				currentModule(NULL),
				gmake(true),
				universe(TARGET_UNIVERSE_STANDARD)
			{}
		};
		
		inline char * save_str(const char *s){
			char *p;
			p = new char[strlen(s)+1];
			strcpy(p,s);
			return(p);
		}
		
		inline double * save_float(float d){
			double *dp;
			dp = new double;
			*dp = d;
			return(dp);
		}
		
		
		typedef GenExpr * expr;
		
		expr compile_required(expr x);
		expr compile_backend(expr x);
		expr compile_shrink(expr x);
		expr compile_language(expr x);
		expr compile_calcorder(expr x);
		
		void compile_MODULE(expr x);
		void compile_FORTRANFORMAT(expr x);
		void compile_FORTRANSTRINGCONVENTION(expr x);
		void compile_COMPILE_OPTIONS(expr x);
		void compile_GLOBALS(expr x);
		void compile_LIBRARY(expr x);
		void compile_interface(expr def, expr desc, expr option_list, expr body);
		void compile_class(expr name, expr desc_string, expr option_list, 
											 expr def_list);
		void compile_linker(expr x);
		void compile_compiler(expr x);
		
#ifdef NC_GEN_MAIN
		GenGlobals ncGenGlobals;
#else
		extern GenGlobals ncGenGlobals;
#endif
		
		void error(const char * fmt, ...);
		void fatal(const char * fmt, ...);
		void error_at_node(expr x, const char *fmt, ...);
		
	}
}		

#endif
